﻿
Namespace Navigation
    Public Class Session

        Private _NextId As Integer = 0
        Private _IdLock As New Object
        Private _ReferenceStore As Dictionary(Of Integer, WeakReference) = New Dictionary(Of Integer, WeakReference)

        Private Function GetId() As Integer
            Dim result As Integer
            SyncLock _IdLock
                Try
                    result = _NextId
                    _NextId += 1
                Catch ex As Exception
                    _NextId = 0
                    result = -1
                End Try
            End SyncLock
            Return result
        End Function

        Private Sub CollectGarbage()
            Dim list() As KeyValuePair(Of Integer, WeakReference) = _ReferenceStore.ToArray
            For Each e As KeyValuePair(Of Integer, WeakReference) In list
                If Not e.Value.IsAlive Then
                    _ReferenceStore.Remove(e.Key)
                End If
            Next
        End Sub

        Public Function StoreReference(ByVal reference As Object) As Integer
            Dim id As Integer = -1
            If reference IsNot Nothing Then
                id = GetId()
                Dim weakReference As WeakReference = New WeakReference(reference)
                _ReferenceStore.Add(id, weakReference)
            End If
            Return id
        End Function

        Public Function StoreReference(ByVal id As Integer, ByVal reference As Object) As Integer
            Dim result As Integer = id
            If _ReferenceStore.ContainsKey(id) Then
                If reference Is Nothing Then
                    _ReferenceStore.Remove(id)
                    result = -1
                Else
                    _ReferenceStore.Item(id) = New WeakReference(reference)
                End If
            Else
                result = StoreReference(reference)
            End If
            Return result
        End Function

        Public Function RetrieveReference(ByVal id As Integer) As Object
            Dim result As Object = Nothing
            GC.Collect()
            If id <> -1 AndAlso _ReferenceStore.ContainsKey(id) Then
                result = _ReferenceStore.Item(id).Target
                If result Is Nothing Then
                    _ReferenceStore.Remove(id)
                    CollectGarbage()
                End If
            End If
            Return result
        End Function

        Public Sub FreeReference(ByVal id As Integer)
            _ReferenceStore.Remove(id)
        End Sub
    End Class
End Namespace
